#include <regx52.h>
#include "timer.c"

/**
 * 等待用户出拳，点击按钮代表出拳石头剪刀布。系统随机出拳。
 * 决出胜负，胜利方灯亮。点击按钮重新开始游戏。
 */

typedef enum
{
    ROCK,
    SCISSORS,
    PAPER
} GuessType;

GuessType user_choice;
GuessType compute_choice;

typedef enum
{
    USER_WIN,
    COMPUTER_WIN,
    DRAW
} Result;

#define STATE_BEGIN 0
#define STATE_END 1

unsigned char state = STATE_BEGIN;

sbit BTN_START = P1 ^ 0;
sbit BTN_ROCK = P1 ^ 1;
sbit BTN_SCISSORS = P1 ^ 2;
sbit BTN_PAPER = P1 ^ 3;

#define BTN_CODE_START 0
#define BTN_CODE_ROCK 1
#define BTN_CODE_SCISSORS 2
#define BTN_CODE_PAPER 3

#define LEDS P2
sbit LED_USER_WIN = P2 ^ 0;
sbit LED_USER_ROCK = P2 ^ 1;
sbit LED_USER_SCISSORS = P2 ^ 2;
sbit LED_USER_PAPER = P2 ^ 3;

sbit LED_COMPUTER_WIN = P2 ^ 7;
sbit LED_COMPUTER_ROCK = P2 ^ 6;
sbit LED_COMPUTER_SCISSORS = P2 ^ 5;
sbit LED_COMPUTER_PAPER = P2 ^ 4;

void delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
    {
        for (j = 0; j < 123; j++)
            ;
    }
}

unsigned char btn_scan()
{
    unsigned char rlt = 0xFF;
    if (BTN_START == 0)
    {
        delay_ms(20);
        if (BTN_START == 0)
        {
            rlt = BTN_CODE_START;
            while (BTN_START == 0)
                ;
        }
    }

    if (BTN_ROCK == 0)
    {
        delay_ms(20);
        if (BTN_ROCK == 0)
        {
            rlt = BTN_CODE_ROCK;
            while (BTN_ROCK == 0)
                ;
        }
    }

    if (BTN_SCISSORS == 0)
    {
        delay_ms(20);
        if (BTN_SCISSORS == 0)
        {
            rlt = BTN_CODE_SCISSORS;
            while (BTN_SCISSORS == 0)
                ;
        }
    }

    if (BTN_PAPER == 0)
    {
        delay_ms(20);
        if (BTN_PAPER == 0)
        {
            rlt = BTN_CODE_PAPER;
            while (BTN_PAPER == 0)
                ;
        }
    }
    return rlt;
}

Result play_result()
{
    if (
        (user_choice == ROCK && compute_choice == SCISSORS) ||
        (user_choice == SCISSORS && compute_choice == PAPER) ||
        (user_choice == PAPER && compute_choice == ROCK))
    {
        return USER_WIN;
    }

    if (
        (compute_choice == ROCK && user_choice == SCISSORS) ||
        (compute_choice == SCISSORS && user_choice == PAPER) ||
        (compute_choice == PAPER && user_choice == ROCK))
    {
        return COMPUTER_WIN;
    }

    return DRAW;
}

void process_game_begin()
{
    unsigned char btn_code = btn_scan();

    switch (btn_code)
    {
    case BTN_CODE_ROCK:
        LED_USER_ROCK = 0;
        user_choice = ROCK;
        break;
    case BTN_CODE_SCISSORS:
        LED_USER_SCISSORS = 0;
        user_choice = SCISSORS;
        break;
    case BTN_CODE_PAPER:
        LED_USER_PAPER = 0;
        user_choice = PAPER;
        break;
    default:
        break;
    }

    if (btn_code != 0xFF && btn_code != BTN_CODE_START)
    {
        timer_seed = get_timer0_value();
        compute_choice = timer_rand() % 3;

        switch (compute_choice)
        {
        case ROCK:
            LED_COMPUTER_ROCK = 0;
            break;
        case SCISSORS:
            LED_COMPUTER_SCISSORS = 0;
            break;
        case PAPER:
            LED_COMPUTER_PAPER = 0;
            break;
        default:
            break;
        }

        state = STATE_END;
        switch (play_result())
        {
        case USER_WIN:
            LED_USER_WIN = 0;
            break;
        case COMPUTER_WIN:
            LED_COMPUTER_WIN = 0;
            break;
        default:
            break;
        }
    }
}

void process_game_end()
{

    unsigned char btn_code = btn_scan();

    switch (btn_code)
    {
    case BTN_CODE_START:
        LEDS = 0xFF;
        state = STATE_BEGIN;
        break;
    default:
        break;
    }
}

void main()
{
    timer0_init();
    while (1)
    {
        switch (state)
        {
        case STATE_BEGIN:
            process_game_begin();
            break;
        case STATE_END:
            process_game_end();
            break;
        default:
            break;
        }
    }
}
